---
menu: Active Proposals
name: Combobox (Explainer)
path: /components/combobox.explainer
pathToResearch: /components/combobox.research
layout: ../../layouts/ComponentLayout.astro
---
import Image from '../../components/image.astro'

- [@sudheer-gowrgiari](https://github.com/sudheer-gowrigari), [@gregwhitworth](https://github.com/gregwhitworth), [@josepharhar](https://github.com/josepharhar)
- Last updated: October 31, 2025
- Feedback: https://github.com/openui/open-ui/issues/924

## Table of Contents

- [Background](#background)
- [Use cases](#use-cases)
- [Styling the input and datalist elements with base appearance](#styling-the-input-and-datalist-elements-with-base-appearance)
- [Associating an input element with a select element](#associating-an-input-element-with-a-select-element)
- [Making your own picker for a filterable select](#making-your-own-picker-for-a-filterable-select)
- [Datalist becomes a popover](#datalist-becomes-a-popover)
- [Options, focus, and keyboard behavior](#options-focus-and-keyboard-behavior)
- [Rendering filtered options](#rendering-filtered-options)
- [Controlling the filtering behavior](#controlling-the-filtering-behavior)
  - [The `search` attribute](#the-search-attribute)
  - [The `beforefilter` event](#the-beforefilter-event)
- [Option element attributes](#option-element-attributes)
- [Examples](#examples)
  - [Basic](#basic)
- [Design decisions](#design-decisions)

## Background

The combobox element currently supported by browsers by connecting an `<input type=text>` element to a `<datalist>` element does not provide enough customization for web developers, which leads them to implement their own. These implementations can lead to reduced performance, reliability, and accessibility compared to the native form control elements. More on that is in [Custom Control UI](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ControlUICustomization/explainer.md#introduction).

OpenUI made a [Twitter poll](https://twitter.com/openuicg/status/1717345237889351911) which underscored the widespread demand for a customizable combobox:
<Image
  src="/images/combobox/combobox-twitterpoll.png"
  alt="Poll results which shows more interest in combobox than listbox, tooltip, or range/slider."
/>

In addition to the combobox use case where arbitrary text typed in by the user is acceptable, filtering a list of predefined options and forcing the user to choose one is an important use case. The `<select>` element is ideal for this and has been improved with the customizable select feature, but it does not support filtering the list of options.

This [survey](https://www.gwhitworth.com/posts/2019/can-we-please-style-select/#:~:text=Not%20being%20able%20to%20create%20a%20good%20user%20experience%20for%20searching%20within%20the%20list) shows that the number one request for enhancement of the `<select>` element is the ability to filter the options.

This proposal adds three pieces of functionality required to achieve these use cases:
* Stylability for `<input type=text>` with `<datalist>` via `appearance:base`.
* Filtering for `<select>` elements by adding the ability to connect an `<input>` to a `<select>` element.
* Powerful filtering primitives for both of the above cases.

## Use cases

* Arbitrary styling for the datalist picker and its options:
  * Basic properties such as colors, padding, and font
  * Advanced styling such as highlighting individual characters in an option which the user searched for or changing styles of the filtered options
* Replacing the default filtering behavior with:
  * Basic types of alternate filtering, like startsWith or pattern
  * Advanced filtering where a JS API can be used to replace the filtering entirely
* Dynamically and asynchronously adding options in response to text added to the input element
  * This enables fetching options from a server and appending them into the datalist in response to the user typing into the input element, as well as DOM virtualization

The labels picker on github is a target use case which could be solved by creating a dialog which contains an input element with a select element where the input is linked to the select to perform filtering:
<Image
  src="/images/combobox/githublabels.gif"
  alt="A video of the labels picker popup on the github website"
/>

The search bar on github is a target use case which could be solved by creating an input element which links to a datalist with base appearance:
<Image
  src="/images/combobox/githubsearch.gif"
  alt="A video of the search box on the github website"
/>

## Styling the input and datalist elements with base appearance

The `<input>` and `<datalist>` elements will continue to render as they currently do unless they both have the `appearance:base` CSS propety applied to them.

Here is a basic example:
```html
<input list=datalist style="appearance:base">
<datalist id=datalist style="appearance:base">
  <option>one</option>
  <option>two</option>
</datalist>
```

## Associating an input element with a select element

The `<input type=text>` element can be associated with a `<select>` element with the new `filter` attribute. The select element must be rendered as a listbox, not as a drop-down box.

```html
<input filter=select>
<select id=select size=4>
  <option>one</option>
  <option>two</option>
</select>
```

## Making your own picker for a filterable select

Unlike alternative proposals which allowed the author to put a filtering input inside a drop-down select element, this proposal requires the author to make their own picker containing a listbox select element like this:

```html
<button popovertarget=picker>
  <selectedcontent for=select></selectedcontent>
</button>
<dialog popover id=picker>
  <input filter=select>
  <select size=4 id=select>
    <option>one</option>
    <option>two</option>
  </select>
</dialog>
```

## Datalist becomes a popover

When the datalist element has base appearance, it will automatically become a popover without the need for the author to set the popover attribute on it. When the input element is focused, the datalist will be shown as a popover and anchored to the input element.

When the input element pointing to a datalist receives focus, it will show the datalist popover.

Option elements inside of a datalist are not keyboard focusable because focus is intented to always stay inside of the input element.

## Options, focus, and keyboard behavior

In both the input-with-datalist and input-with-select cases, in order to allow the user to simulatenously type characters into the input element and choose options with the arrow keys and the enter key, the input element will remain focused and the option which will be selected when pressing enter has the `:focused-option` pseudo-class.

Pressing the down arrow key will move the `:focused-option` pseudo-class forwards one option element in DOM order. The up arrow key will move the pseudo-class backwards one option element in DOM order.

## Rendering filtered options

In both the input-with-datalist and input-with-select cases, option elements which are being filtered out will have the `:filtered` pseudo-class set on them. There will be a UA style rule which sets `display:none` on `option:filtered` elements.

## Controlling the filtering behavior

The filtering behavior can be controlled by either setting the `search` attribute on the input element or by listening to the `beforefilter` event on the input element.

### The `search` attribute

Without the `search` attribute, the browser will decide how to do filtering. When the `search` attribute is set, the filtering behavior follows behavior defined by the supported attribute values:
* `pattern`: Matches options against a pattern. For example, typing "^a" finds options starting with "a". definition [here](https://html.spec.whatwg.org/#the-pattern-attribute).
* `startswith`: Shows options that start with the user’s input. Typing "Ap" will display "Apple" and "Apricot" but not "Banana". Definition [here](https://tc39.es/ecma262/multipage/text-processing.html#sec-string.prototype.startswith).
* `includes`: Searches anywhere in the option text. Typing "a" will display "Apple", "Apricot", and "Banana". definition [here](https://tc39.es/ecma262/multipage/text-processing.html#sec-string.prototype.includes).

### The `beforefilter` event

The `beforefilter` event is fired on the input element before the browser runs its filtering algorithm and applies the `:filtered` pseudo-class to option element. When the `beforefilter` event is `preventDefault()`ed, the browser does not run its filtering algorithm and script is free to implement whatever filtering it likes, such as removing all the option elements and re-appending relevant options.

## Option element attributes

Option elements rendered in a base appearance datalist will not render their label or value attributes. When an option is selected, its value attribute will be used to set the text inside of the input element in order to match the default native appearance.

## Keyboard behavior
Details regarding keyboard interaction for the combobox will follow the [W3C ARIA Authoring Practices for combobox patterns](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). For further development and discussions, please see the [filed issue](https://github.com/openui/open-ui/issues/929).


## Multi-select combobox use case

Several libraries offer a combobox where each selected option becomes added to a list of options at the start of the combobox:
- https://primer.style/product/components/autocomplete/#multi-select-with-tokens-for-selected-items
- https://select2.org/getting-started/basic-usage#multi-select-boxes-pillbox

This explainer provides useful primitives for building this use case, but the action of creating a new button to represent the option which was selected is best left to script.

## Examples

{/* TODO add more examples and use code-image-container */}

### Basic

This example changes some padding, colors, and styling of the selected option.

```html
<input list=datalist>
<datalist id=datalist>
  <option>one</option>
  <option>two</option>
</datalist>
<style>
input, datalist {
  appearance: base;
}
input {
  border-radius: 0.5em;
  font-family: monospace;
}
datalist {
  border-radius: 0.5em;
}
option:focused-option {
  background-color: lightblue;
}
</style>
```

## Design decisions

- [Why not create a new combobox element](https://github.com/openui/open-ui/issues/1273)
- [Why not make the author put the popover attribute on datalist](https://github.com/openui/open-ui/issues/703)
- Why not put `<input>` inside `<select>`
  - https://github.com/openui/open-ui/issues/847#issuecomment-3391813132
  - https://github.com/openui/open-ui/issues/847#issuecomment-3411919639
